package com.cyzy.ws;

import com.cyzy.domain.dto.CustomerServiceDto;
import com.cyzy.domain.dto.MessageDto;
import com.cyzy.service.TAgentService;
import com.cyzy.service.TUserAgentMessageService;
import com.cyzy.utils.MessageUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    @Autowired
    private TUserAgentMessageService tUserAgentMessageService;

    @Autowired
    private TAgentService tAgentService;

    private static final Map<Integer, Set<Integer>> serverUsers = new ConcurrentHashMap<>();
    private static final Map<Integer, Integer> users = new ConcurrentHashMap<>();
    private static final Map<String, WebSocketSession> onlineUsers = new ConcurrentHashMap<>();

    private RedisTemplate<String, String> redis;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocket 连接成功");

        URI uri = session.getUri();
        String path = uri.getPath();
        System.out.println("路径：" + path);
        String[] split = path.split("/");
        CustomerServiceDto curr = new CustomerServiceDto(Integer.parseInt(split[2]), Integer.parseInt(split[3]), 0);

//        String currUser = (String) this.httpSession.getAttribute(this.currUser);
//        CustomerServiceDto curr = new ObjectMapper().readValue(currUser, CustomerServiceDto.class);
        System.out.println("当前登录的用户/客服" + curr);
        // 判断是客服登录还是用户登录
        if (curr.getType() == 1) {
            onlineUsers.put("U" + curr.getUserId(), session);
            // 用户
            // 判断是智能客服还是人工客服
//            if (curr.getSelected() == 1) {
//                // 智能客服
//                handleAutoAgent(session, curr.getUserId());
//            } else if (curr.getSelected() == 2) {
//                System.out.println("选择人工客服");
                // 人工客服
            handleManualAgent(session, curr.getUserId());
//            }
        } else if (curr.getType() == 2) {
            onlineUsers.put("A" + curr.getUserId(), session);
            System.out.println("分配用户");
            // 客服
            handleAgent(session, curr.getUserId());
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("接收到来自客户端的消息： " + message.getPayload());
        // 解析消息数据
        MessageDto msg = new ObjectMapper().readValue(message.getPayload(), MessageDto.class);
        System.out.println("解析消息如下：" + msg);
        Integer toUserId = msg.getToUserId();
        String content = msg.getMessage();

        URI uri = session.getUri();
        String path = uri.getPath();
        String[] split = path.split("/");
        CustomerServiceDto curr = new CustomerServiceDto(Integer.parseInt(split[2]), Integer.parseInt(split[3]), 0);
        // 当前用户
//        String currUser = (String) this.httpSession.getAttribute(this.currUser);
//        CustomerServiceDto curr = new ObjectMapper().readValue(currUser, CustomerServiceDto.class);
        System.out.println(curr + " , " + msg);
        if (curr.getType() == 1) {
            // 如果是用户
            // 结束服务传递消息：direction=3,content=评级
            if (msg.getDirection() == 3) {
                // 如果选择结束服务
                handleUserEndMessage(session, curr.getUserId(), content);
            } else {
                handleUserMessage(session, toUserId, content);
            }
        } else if (curr.getType() == 2) {
            // 如果是客服
            // 结束服务传递消息：direction=3
            if (msg.getDirection() == 3) {
                // 如果选择下班
                handleAgentEndMessage(session, curr.getUserId(), content);
            } else {
                handleAgentMessage(session, toUserId, content);
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        try {
//            if (this.httpSession == null || this.httpSession.getAttribute(this.currUser) == null) {
//                return;
//            }
//            String currUser = (String) this.httpSession.getAttribute(this.currUser);
//            CustomerServiceDto curr = new ObjectMapper().readValue(currUser, CustomerServiceDto.class);
            URI uri = session.getUri();
            String path = uri.getPath();
            System.out.println("路径：" + path);
            String[] split = path.split("/");
            CustomerServiceDto curr = new CustomerServiceDto(Integer.parseInt(split[2]), Integer.parseInt(split[3]), 0);

            Integer type = curr.getType();
            // 判断是客服下班还是用户退出
            // 只能由他们选择下班、换客服才能解除关系，而不是中断联系
            if (type == 1) {
                // 告诉客服用户已离线
                Integer i = users.get(curr.getUserId());
                if (i == null) {
                    // 说明客服没上班，按了个寂寞
                    return;
                }
                WebSocketSession agentSession = onlineUsers.get("A" + i);
                if (agentSession != null) {
                    agentSession.sendMessage(new TextMessage(MessageUtil.setMessage(true, 13, "用户已断开连接。", null)));
                }
            } else if (type == 2) {
                // 告诉用户客服已离线
                if (serverUsers.get(curr.getUserId()) != null) {
                    Set<Integer> usersId = serverUsers.get(curr.getUserId());
                    for (Integer i : usersId) {
                        onlineUsers.get("U" + i).sendMessage(new TextMessage(MessageUtil.setMessage(true, 4, "客服已离线，请发送离线消息或切换客服。", null)));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void handleAutoAgent(WebSocketSession session, Integer userId) throws IOException {
        // 处理智能客服逻辑
        // 例如，从Redis中获取关键词匹配的语句
        String response = redis.opsForValue().get("auto_response_" + userId);
        session.sendMessage(new TextMessage(response));
    }

    private void handleManualAgent(WebSocketSession session, Integer userId) throws IOException {
        // 随机分配客服
        System.out.println("随机分配客服中");
        Integer assignedAgent = assignAgent();
        if (assignedAgent != null) {
            // 分配成功，更新用户和客服的映射
            System.out.println("分配客服成功");
            users.put(userId, assignedAgent);
            serverUsers.get(assignedAgent).add(userId);
            // 通知用户已分配客服
            session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 1, "您已成功分配到客服：" + assignedAgent, assignedAgent)));
            // 通知客服已经被分配到用户
            onlineUsers.get("A" + assignedAgent).sendMessage(new TextMessage(MessageUtil.setMessage(true, 14, "已分配用户" + userId, serverUsers.get(assignedAgent))));
//            if (agentSession != null) {
//                agentSession.sendMessage(new TextMessage(MessageUtil.setMessage(true, 14, "已分配用户" + userId, serverUsers.get(assignedAgent))));
//            }
        } else {
            // 客服繁忙
            System.out.println("客服繁忙，请稍后再试");
            users.put(userId, -1);
            session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 2, "当前所有客服都忙碌，请稍后再试", null)));
        }
    }

    private Integer assignAgent() {
        Integer selectedAgent = null;
        int minUsers = Integer.MAX_VALUE;
        for (Map.Entry<Integer, Set<Integer>> entry : serverUsers.entrySet()) {
            if (entry.getValue().size() < minUsers) {
                minUsers = entry.getValue().size();
                selectedAgent = entry.getKey();
            }
        }
        if (minUsers == Integer.MAX_VALUE) {
            return null; // 没有可用的客服
        }
        return selectedAgent;
    }

    /**
     * 客服登录
     * @param session
     * @param userId
     */
    private void handleAgent(WebSocketSession session, Integer userId) throws IOException {
        if (serverUsers.get(userId) != null && serverUsers.get(userId).size() > 0) {
            System.out.println("查找历史用户");
            session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 14, "已分配历史用户", serverUsers.get(userId))));
            for (Integer i : serverUsers.get(userId)) {
                onlineUsers.get("U" + i).sendMessage(new TextMessage(MessageUtil.setMessage(true, 6, "已为您分配客服：" + userId, userId)));
            }
            return;
        }
        System.out.println("分配未绑定用户中");
        serverUsers.put(userId, new HashSet<Integer>());
        for (Integer key : users.keySet()) {
            if (users.get(key) == -1) {
                System.out.println("绑定用户成功" + key);
                // 用户绑定客服
                users.replace(key, userId);
                // 客服绑定用户
                serverUsers.get(userId).add(key);
                session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 14, "已分配用户" + key, serverUsers.get(userId))));
                onlineUsers.get("U" + key).sendMessage(new TextMessage(MessageUtil.setMessage(true, 1, "您已成功分配到客服：" + userId, userId)));
                return;
            }
        }
        session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 12, "正在分配用户，请耐心等待~", null)));
    }

    private void handleUserEndMessage(WebSocketSession session, Integer userId, String content) throws IOException {
        WebSocketSession agentSession = onlineUsers.get("A" + users.get(userId));
        if (agentSession != null) {
            if (content == null) {
                agentSession.sendMessage(new TextMessage(MessageUtil.setMessage(true, 13, "用户已结束服务。给您默认好评", null)));
            } else {
                agentSession.sendMessage(new TextMessage(MessageUtil.setMessage(true, 13, "用户已结束服务。为您评星级" + content + "星", content)));
            }
            // 回复用户您已结束服务
            session.sendMessage(new TextMessage(MessageUtil.setMessage(true, 5, "结束服务成功", null)));
            // 结束用户session
            serverUsers.get(users.get(userId)).remove(userId);
            users.remove(userId);
            onlineUsers.remove("U" + userId);
        }
    }

    private void handleAgentEndMessage(WebSocketSession session, Integer userId, String content) throws IOException {
        for (Integer i : serverUsers.get(userId)) {
            WebSocketSession userSession = onlineUsers.get("U" + i);
            System.out.println("给用户："  + i + "取消客服");
            userSession.sendMessage(new TextMessage(MessageUtil.setMessage(true, 4, "客服已下班，请刷新页面，重新为您分配客服。", null)));
            if (users != null && users.get(userId) != null) {
                users.put(i, null);
            }
        }
        serverUsers.remove(userId);
        onlineUsers.remove("A" + userId);
    }

    private void handleUserMessage(WebSocketSession session, Integer toUserId, String content) throws IOException {
        // 处理用户消息
        // TODO:存储到Redis和MQ
        // 发送消息到对应的客服
        WebSocketSession agentSession = onlineUsers.get("A" + toUserId);
        if (agentSession != null) {
            agentSession.sendMessage(new TextMessage(MessageUtil.setMessage(false, 0, content, null)));
        }
    }

    private void handleAgentMessage(WebSocketSession session, Integer toUserId, String content) throws IOException {
        // 处理客服消息
        // TODO:存储到Redis和MQ
        // 发送消息到用户
        WebSocketSession userSession = onlineUsers.get("U" + toUserId);
        if (userSession != null) {
            userSession.sendMessage(new TextMessage(MessageUtil.setMessage(false, 0, content, null)));
        }
    }
}